import sys
import threading
import time
import cv2

from PyQt5.QtCore import Qt
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QMessageBox

#from UI.achieve.tools.achieve_train import Achieve
from model_video import *
from file_stream import FileVideoStream
#from common.util.logger import logger
from components import OverlayController, VideoOverlay, push_frame_to_detect, put_fps, CameraSignal


class AIVideo(Ui_MainWindow):


    def __init__(self, main_window, main_instance):
        super(AIVideo, self).__init__()
        # self.frame_signal = Sig()
        self.video_stream = None
        self.video_read_loop = False
        self.main_window = main_window
        self.main_instance = main_instance
        self.setupUi(main_window)
        self.initObject()
        self.initUI()
        self.initButton()
        self.initObject()
        self.video_file_path = ''
        self.toolButton_4.clicked.connect(self.open_img_stream)
        # self.toolButton_2.clicked.connect(self.start_read_frame)
        self.camera_sig = CameraSignal()
        self.camera_sig.frame.connect(self.show_frame)
        self.camera_sig.res_json.connect(self.print_json)
        # self.x = 0
        self.controller = None

        tmp_closeEvent = self.main_window.closeEvent

        def new_closeEvent(event):
            self.stop_read_frame()
            tmp_closeEvent(event)

        self.main_window.closeEvent = new_closeEvent


    def __del__(self):
        self.video_read_loop = False

        if self.video_stream:
            self.video_stream.stop()
            self.controller.stop()
            self.overlay.reset_label()
            # stop_detect_thread()

    def initUI(self):
        pass

    def initButton(self):
        self.toolButton_3.clicked.connect(self.ai_video_update)
        self.toolButton_5.clicked.connect(self.stop_read_frame)
        self.pushButton_2.clicked.connect(self.clear_table_data)
        # self.frame_signal.frame_signal.connect(self.show_frame)

    def initObject(self):
        try:
            self.achieve = Achieve()
            self.overlay = VideoOverlay(self.label_14)
            self.overlay.setGeometry(0, 0, self.label_14.width(), self.label_14.height())
        except Exception as e:
            logger.exception(e)

    def update_overlay(self, rect):
        self.overlay.rectangles = rect
        # 仅更新需要重绘的区域
        self.overlay.update()

    def ai_video_update(self):
        try:
            file = QFileDialog.getOpenFileName(self.main_window, '选择文件', './', 'Video Files (*.mp4 *.avi)')
            print(file)
            if file[0]:
                self.video_file_path = file[0]
                self.label_6.setText(self.video_file_path)
        except Exception as e:
            logger.exception(e)


    def print_json(self, res_json):
        """展示在tableWidget_2"""
        # frame_cnt = self.video_stream.current_frame_index
        for label_dict in res_json:
            self.achieve.insert_tablewidget_row(self.tableWidget_2)
            row_count = self.tableWidget_2.rowCount()
            x1 = int(label_dict['xmin'])
            y1 = int(label_dict['ymin'])
            x2 = int(label_dict['xmax'])
            y2 = int(label_dict['ymax'])
            confidence = label_dict['confidence']
            confidence = round(confidence, 2)
            name = str(label_dict['name'])
            # self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=0, data=str(frame_cnt))
            self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=1, data=name)
            self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=2, data=str(confidence))
            self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=3, data=str(x1))
            self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=4, data=str(y1))
            self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=5, data=str(x2))
            self.achieve.write_table_widget(self.tableWidget_2, row=row_count - 1, column=6, data=str(y2))


    def open_img_stream(self):
        """
        :param path: 视频路径
        开启视频流， 一次性操作
        """
        # 传入帧并展示
        self.video_stream = FileVideoStream(self.video_file_path)
        self.video_stream.start()
        label = [self.lineEdit_9.text()]
        min_confidence = float(self.doubleSpinBox.text())
        if self.controller:
            self.controller.stop()  # 先停止之前的检测线程
            self.overlay.reset_label() # 清空之前的检测框
            # self.controller.wait(0.5)
        self.controller = OverlayController(label, min_confidence)
        # print(self.video_stream.width, self.video_stream.height)
        self.controller.set_pixel(self.video_stream.width, self.video_stream.height)
        self.start_read_frame()

    def start_read_frame(self):
        """
        读取视频帧线程
        """
        if self.video_stream is None:
            return
        self.video_read_loop = True
        self.video_stream.last_frame_index = 0
        self.video_stream.current_frame_index = 0
        thread = threading.Thread(target=self.camera_show)
        thread.start()
        self.controller.update_rect.connect(self.update_overlay)
        self.controller.start()

    def stop_read_frame(self):
        """
        停止读取视频帧,同时关闭视频流
        """
        if self.video_stream is None:
            return
        self.video_read_loop = False
        self.video_stream.stop()
        self.controller.stop()
        self.overlay.reset_label()


    def camera_show(self):
        """
        读取视频功能
        """
        time.sleep(1) # 等待视频流加载
        while self.video_read_loop:
            image_show = self.video_stream.read()

            if image_show is None:
                self.controller.stop()
                self.overlay.reset_label()
                return


            push_frame_to_detect(image_show)
            # image_show = put_fps(image_show)

            if isinstance(image_show, int):
                print('帧丢失')
                continue

            height, width = image_show.shape[:2]
            image_show = cv2.cvtColor(image_show, cv2.COLOR_BGR2RGB)  # opencv读的通道是BGR,要转成RGB
            showImage = QtGui.QImage(image_show.data, width, height, QImage.Format_RGB888)
            showImage = showImage.scaled(self.label_14.width(), self.label_14.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
            self.camera_sig.frame.emit(showImage)
        self.camera_sig.reset_label.emit()

    def show_frame(self, image_show):
        """展示在label_14"""
        self.label_14.setPixmap(QPixmap.fromImage(image_show))
        self.label_14.setScaledContents(True)  # 图片自适应

    def clear_table_data(self):
        try:
            choice = QMessageBox.question(self.main_window, 'INFO', '确定清空？')
            if choice == QMessageBox.Yes:
                self.achieve.clear_table_all_contents(self.tableWidget_2)
            if choice == QMessageBox.No:
                logger.info("取消")
        except Exception as e:
            logger.exception(e)



if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = QMainWindow()
    main_instance = AIVideo(main_window, None)
    main_window.show()
    sys.exit(app.exec_())
